package org.whuims.pois.cluster;

import org.whuims.pois.model.DataC;
import org.whuims.poms.bean.VectorEntity;

import java.util.*;


public class Cluster {

    private List<DataC> list;

    public Cluster(List<DataC> list) {
        this.list = list;
    }

    /**
     * 聚类过程 聚类采用经典的single-pass单向聚类方法
     */
    public void clust() {
        HashMap<Long, String> compared = new HashMap<Long, String>();
        DataC bean1;
        DataC bean2;
        for (int i = 0; i < list.size(); i++) {
            bean1 = list.get(i);

            if (compared.containsKey(new Long(bean1.getId()))) {
                continue;
            }

            for (int j = i + 1; j < list.size(); j++) {
                bean2 = list.get(j);

                if (compared.containsKey(new Long(bean2.getId()))) {
                    continue;
                }

                boolean isSimilar = similarity(bean1, bean2);
                if (isSimilar) {
                    bean1.addSimilar(bean2);
                    compared.put(new Long(bean2.getId()), "unseeds");
                }
            }
        }
        /** 对list排序，按照他们所包含的相似记录个数排序 */
        Collections.sort(list, new Comparator<DataC>() {
            public int compare(DataC bean1, DataC bean2) {
                if (bean1.getSimilarList().size() < bean2.getSimilarList()
                        .size()) {
                    return 1;
                } else if (bean1.getSimilarList().size() > bean2.getSimilarList().size()) {
                    return -1;
                } else {
                    return 0;
                }
            }
        });
        /** 剔除队列中无相似记录的记录 */
        Iterator<DataC> it = list.iterator();
        while (it.hasNext()) {
            DataC bean = it.next();
            if (bean.getSimilarList().size() == 0) {
                it.remove();
            }
        }
    }

    /**
     * 计算两个对象的相似性，可以考虑全文、标题、实体等特征
     */
    private boolean similarity(DataC bean1, DataC bean2) {
        /** 全文相似度 */
        VectorEntity vectorEntity1 = bean1.getVector();
        VectorEntity vectorEntity2 = bean2.getVector();
        if (vectorEntity1 == null || vectorEntity2 == null) {
            return false;
        }
        float[] v1 = vectorEntity1.getVector();
        float[] v2 = vectorEntity2.getVector();

        float contentSimilarity = similarValue(v1, v2);
        if (contentSimilarity > 0.3) {
            System.out.println("content: " + contentSimilarity);
        }
        if (contentSimilarity > 0.7) {
            return true;
        } else {
            List<DataC> list = bean1.getSimilarList();
            for (DataC bean : list) {
                if (similarity(bean, bean2)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断两个数组的余弦值，看其是否在聚类阀值内
     */
    private float similarValue(float[] v1, float[] v2) {
        if (v1.length != v2.length) {
            return 0.0f;
        }
        float cos = 0.0f;
        float length1 = 0.0f, length2 = 0.0f;
        for (int i = 0; i < v1.length; i++) {
            cos += v1[i] * v2[i];
            length1 += v1[i] * v1[i];
            length2 += v2[i] * v2[i];
        }
        float value = (float) (cos / (Math.sqrt(length1) * Math.sqrt(length2)));
        return value;
    }


}
